#pragma once
#include "Runtime/Log/Logger.h"

namespace Alice
{
	template<typename T>
	class SmartPtr
	{
	public:
		SmartPtr(T*ptr=nullptr) :mPtr(ptr) { if (nullptr!=mPtr){ mPtr->retain(); }}
		SmartPtr(SmartPtr<T>& inOther) :mPtr(inOther.mPtr) { if (nullptr!=mPtr){ mPtr->retain(); }}
		SmartPtr(const SmartPtr<T>& inOther) :mPtr(inOther.mPtr) { if (nullptr!=mPtr){ mPtr->retain(); }}
		~SmartPtr() { if (mPtr != nullptr) { mPtr->release(); } }
		T*mPtr;
		T* operator ->() { return mPtr; }
		T* operator ->() const { return mPtr; }
		T& operator*() {  return *mPtr;}
		bool operator==(const T* ptr) { return mPtr == ptr; }
		bool operator!=(const T* ptr) { return mPtr != ptr; }
		bool operator==(const T* ptr)const{ return mPtr == ptr; }
		bool operator!=(const T* ptr)const{ return mPtr != ptr; }
		bool operator==(const SmartPtr<T>& r) { return mPtr == r.mPtr; }
		void operator=(SmartPtr<T>&inR) {
			if (inR.mPtr!=nullptr){
				inR->retain();
			}
			if (mPtr!=nullptr){
				mPtr->release();
			}
			mPtr = inR.mPtr;
		}
		void operator=(T* ptr) {
			if (ptr != nullptr) {
				ptr->retain();
			}
			if (mPtr != nullptr)
				mPtr->release();
			mPtr = ptr;
		}
		T* GetReference() { return mPtr; }
		T* GetPtr() { return mPtr; }
		T* GetReference() const { return mPtr; }
		T* GetPtr() const { return mPtr; }
	};
	template<typename T>
	bool operator!=(const T* ptr,const SmartPtr<T>& smartPtr) {
		return ptr != smartPtr.mPtr;
	}
	template<typename T>
	bool operator==(const T* ptr, const SmartPtr<T>& smartPtr) {
		return ptr == smartPtr.mPtr;
	}
}
